home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / patches / thinkc.sit / Think ƒ / printf-3.c < prev    next >
Text File  |  1989-02-25  |  20KB  |  893 lines

  1. /*
  2.     printf formatter for LightspeedC
  3.  
  4.     (C) Copyright 1985, 1986. THINK Technologies, Inc.  All rights reserved.
  5.  
  6.     pdg - 6/11/86 - revised
  7. */
  8.  
  9. /* comment this out if you don't need floating point numeric support */
  10. #define    _FORMAT_FP_
  11.  
  12. #ifndef _stdioh_
  13. #include "stdio.h"
  14. #endif
  15.  
  16. #ifndef    _MacTypes_
  17. #include "MacTypes.h"
  18. #endif
  19.  
  20. #ifndef _saneh_
  21. #include "sane.h"
  22. #endif
  23.  
  24. #ifndef _setjmph_
  25. #include "setjmp.h"
  26. #endif
  27.  
  28. #ifndef _math_
  29. #include "Math.h"
  30. #endif
  31.  
  32. #ifdef _MC68881_
  33. /* conversion from 68881 to SANE extended type */
  34. static void x96tox80(x96, x80)
  35. register Extended96 *x96;
  36. register Extended80 *x80;
  37.  
  38. {
  39.     (*x80).exponent = (*x96).exponent;
  40.     (*x80).mantissa = (*x96).mantissa;
  41. }
  42.  
  43. #define _tox80() x96tox80(doublep, &x80);
  44. #define _ToDecimal() fp68k(&_decform_, &x80, &_decimal_, FFEXT+FOB2D)
  45.  
  46. #else
  47.  
  48. #define _tox80()
  49. #define _ToDecimal() fp68k(&_decform_, doublep, &_decimal_, FFEXT+FOB2D)
  50.  
  51. #endif
  52.  
  53. /* it turns out that defining min, max, and isdigit as follows works pretty
  54.      well and drags in less code from other modules */
  55. #undef min
  56. #undef max
  57. #undef isdigit
  58.     
  59. #define    min(a,b)    ( (a<b) ? (a) : (b) )
  60. #define    max(a,b)    ( (a>b) ? (a) : (b) )
  61. #define isdigit(c)    ( (c<='9') && (c>='0') )
  62.  
  63. #define BLANKS          0
  64.  
  65. void (*_output)();        /* global pointer to function for output */
  66. int _num_count;            /* number of characters transmitted    */
  67. jmp_buf    env;            /* global error return mechanism */
  68.  
  69. static char _hex_case;    /* used for x X case */
  70. static char    fillchar;    /* space or '0' depending on mode */
  71. static int base;        /* global to store base under conversion */
  72.  
  73. #line 0 check_for_three()
  74. static char *check_for_three(ptr,tptr)
  75. char *ptr,*tptr;
  76. {
  77. int l;
  78.  
  79.     /* if length of exponent is 3 or more then return */
  80.  
  81.     if ((l =len_of_str(ptr))>2) return(tptr);
  82.  
  83.     /* This implementation normally makes the exponent 3 bytes wide */
  84.  
  85.     *tptr++ = '0';                /* make default width = 2 */
  86.     
  87.     /* if 2 byte default width is desired then comment out the
  88.          following line of code */
  89.          
  90.     if (l == 1) *tptr++ = '0';  /* make default width = 3 */
  91.  
  92.     return(tptr);
  93. }
  94.  
  95. #line 0 dumpbuffer()
  96. static void dumpbuffer(tbufptr)  /* write buffer to output stream */
  97. register char *tbufptr;
  98. {
  99. register void (*outputx)() = _output;
  100.  
  101.     if (*tbufptr == '@') tbufptr++;
  102.  
  103.      while (*tbufptr)
  104.          (*outputx)(*tbufptr++);
  105.  
  106. }
  107.  
  108. #line 0 dopadding()
  109. static void dopadding(tempbuffer,left_justify,zero_fill,width)
  110. register char *tempbuffer;
  111. register Boolean left_justify,zero_fill;
  112. register int width;
  113. {
  114. register int length;
  115. register void (*outputx)() = _output;
  116.  
  117.     if ((length = len_of_str(tempbuffer))<width)
  118.     {
  119.         width -= length;
  120.          if (left_justify == false)
  121.          {
  122.              if ((*tempbuffer == ' ')||
  123.                  (((*tempbuffer == '+')||(*tempbuffer == '-'))&&zero_fill) )
  124.              {
  125.                  (*outputx)(*tempbuffer);
  126.                  
  127.                  *tempbuffer = '@';
  128.              }
  129.  
  130.              while (--width >= 0)
  131.                  (*outputx)(zero_fill?'0':' ');
  132.                      
  133.              dumpbuffer(tempbuffer);
  134.          }
  135.          else
  136.          {
  137.              dumpbuffer(tempbuffer);
  138.              
  139.              while (--width >= 0)
  140.                  (*outputx)(' ');
  141.          }
  142.       }
  143.       else                            /* pdg - 7/23/86 missing else! */
  144.           dumpbuffer(tempbuffer);
  145. }
  146.  
  147. /* pdg - 6/10/86 - revise for efficiency */
  148.  
  149. #line 0 len_of_str()
  150. static int    len_of_str(s)
  151. register char *s;
  152. {
  153. register char *s0 = s;
  154.  
  155.     while (*s) s++;
  156.     
  157.     return(s-s0);
  158. }
  159.  
  160. #line 0 padd()
  161. static void padd(zero_fill,count)
  162. Boolean    zero_fill;
  163. register int count;
  164. {
  165.     while (--count >= 0)
  166.         (*_output)(((zero_fill)?'0':' '));
  167. }
  168.  
  169.  
  170. #line 0 output_number()
  171. static void output_number(value)
  172. unsigned long value;
  173. {
  174. unsigned long quotient;
  175. register int remainder;
  176.  
  177.     if ((quotient = value / base) != 0) output_number(quotient);
  178.     
  179.     remainder = (value % base);
  180.     
  181.     (*_output)(((remainder<10) ? remainder + '0' :
  182.                                     remainder + _hex_case));
  183. }
  184.  
  185. #line 0 length of number()
  186. static int    length_of_number(number)
  187. register unsigned long number;
  188. {
  189. register int places = 1;
  190.  
  191.     while (number /= base) places++;
  192.     
  193.     return (places);
  194. }
  195.  
  196. #ifdef _FORMAT_FP_
  197.  
  198. char *PtoCstr();    /* need proper typing of return value */
  199.  
  200. #line 0 cvtf2string()
  201. static char *cvtf2string(doublep, style, digits, floatbufferp)
  202. double *doublep;
  203. char style;
  204. short digits;
  205. char *floatbufferp;
  206. {
  207. DecForm _decform_;    /* information record for conversion */
  208. Decimal _decimal_;    /* intermediate record */
  209.  
  210. #ifdef _MC68881_
  211. Extended80 x80;
  212. #endif
  213.  
  214.     /* convert double to Extended80 (as defined in Math881.h) */
  215.     _tox80();
  216.     
  217.     /* convert binary to decimal record */
  218.     
  219.     _decform_.style = style;            
  220.     _decform_.digits = digits;
  221.     
  222.     _ToDecimal();
  223.     
  224.     /* decimal record to string */
  225.     
  226.     _decform_.style= style;        
  227.     _decform_.digits = digits;
  228.     
  229.     Dec2Str(_decform_, &_decimal_, floatbufferp);
  230.     
  231.     /* convert to C string from Pascal string used by SANE */
  232.     
  233.     return (PtoCstr(floatbufferp));
  234. }
  235.  
  236. #endif _FORMAT_FP_
  237.  
  238.  
  239. #line 0 _format()
  240. /*----------------------------------------------------------------------------
  241.   "_format" is the internal routine to do the conversion process. This routine
  242.   is passed a pointer to the pointer to the format string. By scanning the
  243.   format string until a format code is encountered, information can be extrac-
  244.   ted to determine the what argument was present on the stack and processing
  245.   can be handled. Note that the following stack layout applies after the call
  246.   to _format (standard C calling conventions):
  247.  
  248.                 HI memory
  249.                         |---------------------|
  250.                         | last argument       | last argument for format
  251.                         |---------------------|
  252.                                    .
  253.                                    .
  254.                         |---------------------|
  255.                 |--->---| first argument      | points to format string
  256.                 |       |---------------------|
  257.                 |       | return address      |
  258.                 |       |---------------------|
  259.                 |---<---| argument to _format | points to pointer to format
  260.                         |---------------------|
  261.                         | return address      |
  262.                         |---------------------|
  263.                 LO memory
  264.  
  265.   The _format routine sets "format" to point to the format string and scans
  266.   over it. By incrementing the parameter "ptr" (passed to _format) the
  267.   first argument for substitution in the format string can be accessed.
  268.   How the arguments are interpreted is derived from the format string.
  269.   A pointer to a function "*_output" is used to stuff processed characters
  270.   to their destination.
  271.  
  272. -----------------------------------------------------------------------------*/
  273. int _format(fmt,var_stuff)
  274. char **fmt;            /* pointer to pointer to format string */
  275. Boolean    var_stuff;
  276. {
  277. Boolean left_justify;           /* flag to indicate left justiccation */
  278. Boolean do_precision;           /* flag limited precision */
  279. Boolean its_a_long;             /* flag to indicate long integer */
  280. Boolean zero_fill;              /* flag to indicate padding with zero */
  281. Boolean sign_on;                 /* flag to indicate '+' */
  282. Boolean space_on;                  /* flag to indicate ' ' */
  283. Boolean pound_on;                /* flag to indicate '#' */
  284. Boolean    neg;                    /* flag to indicate a negative number */
  285.  
  286. register char *format;            /* pointer to format string */
  287. register char *argument;        /* pointer to arguments for fmt string */
  288.  
  289. #ifdef _FORMAT_FP
  290. #define outputx    _output
  291. #else
  292. register void (*outputx)() = _output;
  293. #endif
  294.  
  295. register char c;                /* current character under inspection */
  296. unsigned long value;            /* for conversion of numerics */
  297. register int length;            /* length of argument to be inserted */
  298. register int width;                /* field width as specified by format */
  299. register int numleft;            /* # of characters left to print */
  300. register int precision;            /* precision of number to be converted */
  301.  
  302. #ifdef _FORMAT_FP_
  303.  
  304. /* floating point junk */
  305. double tempdouble;
  306. char floatbuffer[256];
  307. char tempbuffer[256];
  308. register char *bufptr;
  309. register char *tbufptr;
  310.  
  311. #endif _FORMAT_FP_
  312.  
  313.     /* set up the direct error return to caller */
  314.     
  315.     if (setjmp(env)) return (EOF);
  316.  
  317.     _num_count = 0;                /* set # characters transmitted to zero    */
  318.  
  319.     format = *fmt++;            /* set "format" to the format string */
  320.                                 /* "fmt" is left pointing to first argument */
  321.     argument = (char *) fmt;    /* set "argument" to point to first argument */
  322.  
  323.     /* if variable, indirect through first argument to find real arg list */
  324.  
  325.     if (var_stuff) argument = (char *)(*(long *)argument);
  326.  
  327.     while (c = *format++)           /* scan format string until NULL */
  328.     {
  329.         if (c == '%')
  330.         {
  331.             left_justify     = false;
  332.             zero_fill         = false;
  333.             sign_on         = false;
  334.             space_on         = false;
  335.             pound_on         = false;
  336.             neg                = false;
  337. flagloop:
  338.             switch(c = *format++)
  339.             {
  340.             case '-':    left_justify = true;
  341.                         zero_fill = false;
  342.                         goto flagloop;
  343.  
  344.             case '0':    zero_fill = (!left_justify);
  345.                         goto flagloop;
  346.  
  347.             case '+':    sign_on = true;
  348.                         space_on = false;
  349.                         goto flagloop;
  350.  
  351.             case ' ':    space_on = (!sign_on);
  352.                         goto flagloop;
  353.  
  354.             case '#':    pound_on = true;
  355.                         goto flagloop;
  356.  
  357.             case '*':    numleft = width = *(int *)argument;
  358.                         argument += sizeof(int);
  359.                         goto getdot;
  360.  
  361.             default:    format--;    /* need to back up if unrecognized */
  362.                         break;
  363.             }
  364.  
  365.  
  366.             /* compute total field width */
  367.             
  368.             {char *tempformat = format;    /* let format be register */
  369.             
  370.                 numleft = width = (isdigit(*format)) ? _std_decode(&tempformat) : 0;
  371.                 format = tempformat;
  372.             }
  373.             
  374. getdot:
  375.             /* compute precision within total field width */
  376.  
  377.             precision = 0;
  378.             
  379.             if (do_precision = (*format == '.'))
  380.             {
  381.                 if (*++format == '*')
  382.                 {
  383.                     precision = *(int *)argument;
  384.                     argument += sizeof(int);
  385.                     format++;
  386.                 }
  387.                 else
  388.                 {char *tempformat = format; /* let format be register */
  389.                 
  390.                         precision = _std_decode(&tempformat);
  391.                         format = tempformat;
  392.                 }
  393.             }
  394.  
  395.             if (*format == '%')
  396.             {
  397.                 if (left_justify)
  398.                 {
  399.                     (*outputx)('%');
  400.                     padd(BLANKS,width-1);
  401.                 }
  402.                 else
  403.                 {
  404.                     padd(zero_fill,width-1);
  405.                     (*outputx)('%');
  406.                 }
  407.                 format++;
  408.                 continue;
  409.             }
  410.  
  411.             /* check if long integer is required */
  412.  
  413.             if (its_a_long = ((c = (*format++)) == 'l'))
  414.                 c = *format++;
  415.  
  416.             /* check for short %h.. */
  417.             
  418.             if (c == 'h') c = *format++;
  419.  
  420.             /* note that "format" is left ready for the next pass */
  421.             switch (c)
  422.             {
  423.  
  424.             case 'd':
  425.                 {register long svaluel;    /* for conversion of signed long */
  426.                  register int svaluei;    /* for conversion of signed int */
  427.  
  428.                         if (its_a_long)
  429.                         {
  430.                             svaluel = *(long *)argument;
  431.                             argument += sizeof(long);
  432.                             
  433.                             value = (unsigned long)svaluel;
  434.                             
  435.                             if (svaluel < 0) goto negate;
  436.                         } 
  437.                         else
  438.                         {
  439.                             svaluei = *(int *)argument;
  440.                             argument += sizeof(int);
  441.                             
  442.                             value = (unsigned long)svaluei;
  443.  
  444.                             if (svaluei < 0)
  445.                             {
  446. negate:                            neg = true;
  447.                                 value = -value;
  448.                             }
  449.                         }
  450.                         
  451.                         /* fall into case 'u' */
  452.                 }
  453.                 
  454.             case 'u':
  455.                         base = 10;
  456.                         goto evaluate;
  457.  
  458.             case 'o':
  459.                         base = 8;
  460.                         goto evaluate;
  461.  
  462.             case 'x':    _hex_case = 'a'-10;
  463.                         goto sethex;
  464.             case 'X':
  465.                         _hex_case = 'A'-10;
  466. sethex:
  467.                         base = 16;
  468. evaluate:
  469.                         /* get the target value in a long,
  470.                             readjust the argument pointer */
  471.                             
  472.                         if (c != 'd')
  473.                         {
  474.                             if (its_a_long)
  475.                             {
  476.                                 value = *(unsigned long *)argument;
  477.                                 argument += sizeof (unsigned long);
  478.                             }
  479.                             else
  480.                             {
  481.                                 value = *(unsigned *)argument;
  482.                                 argument += sizeof (unsigned);
  483.                             }
  484.                         }
  485.                         
  486.         /* get the length of the output string */
  487.         
  488.         length = length_of_number(value);
  489.  
  490.         /* now figure out the positioning */
  491.         
  492.         if (zero_fill)
  493.         {
  494.             if (((neg)||(sign_on)||
  495.                 (space_on)) && (c =='d'))
  496.              {
  497.                 if (neg)
  498.                 {
  499.                     (*outputx)('-');
  500.                 }
  501.                 else
  502.                     (*outputx)((sign_on ? '+' : ' '));
  503.                 
  504.                 numleft--;       /* room for sign */
  505.             }
  506.             
  507.             if    (((c=='o')||(c == 'X')||(c == 'x'))&&(pound_on))
  508.                 {
  509.                     (*outputx)('0');
  510.                     numleft--;
  511.  
  512.                     if (c == 'X') { (*outputx)('X');numleft--; }
  513.                     if (c == 'x') { (*outputx)('x');numleft--; }
  514.                 }
  515.                 
  516.             padd(zero_fill, numleft - max(length,precision));
  517.                 
  518.             if (precision > length)
  519.                 padd(zero_fill,precision-length);
  520.  
  521.             output_number(value);
  522.             
  523.         }
  524.  
  525.         if (left_justify)
  526.         {
  527.             if (c =='d')
  528.             {
  529.                 if (neg)
  530.                 {
  531.                     (*outputx)('-');
  532.                     numleft--;
  533.                 }
  534.                 else
  535.                     if((sign_on)||(space_on))
  536.                     {
  537.                         (*outputx)((sign_on ? '+' : ' '));
  538.                             
  539.                         numleft--;
  540.                     }
  541.             }
  542.  
  543.             if    (((c=='o')||(c == 'X')||(c == 'x'))&&(pound_on))
  544.                 {
  545.                     (*outputx)('0');
  546.                     
  547.                     numleft--;
  548.  
  549.                     if (c == 'X') { (*outputx)('X');numleft--; }
  550.                     if (c == 'x') { (*outputx)('x');numleft--; }
  551.                 }
  552.                 
  553.             padd(true,precision-length);
  554.             
  555.             if(precision-length>0) numleft -= (precision-length);
  556.             
  557.             output_number(value);
  558.             
  559.             numleft -= length;
  560.             
  561.             padd(BLANKS, numleft);
  562.             
  563.         }
  564.  
  565.         if ((!zero_fill)&&(!left_justify))
  566.         {
  567.             if (((neg)||(space_on)||
  568.                 (sign_on)) && (c == 'd'))
  569.             {
  570.                 padd(zero_fill, width - max(length,precision)-1);
  571.                     
  572.                 if (neg)
  573.                 {
  574.                     (*outputx)('-');
  575.                 }
  576.                 else
  577.                     (*outputx)(((sign_on)?'+':' '));
  578.                         
  579.                 padd(true,precision-length);
  580.                 
  581.                 output_number(value);
  582.                 
  583.             } /* normal decimal output with sign */
  584.             else
  585.                 if ((pound_on)&&((c == 'o')||(c == 'X')||(c == 'x')))
  586.                 {
  587.                     numleft = 2;
  588.                     if ( c == 'o') numleft = 1;
  589.                     padd(zero_fill, width - max(length,precision)-numleft);
  590.                         
  591.                     (*outputx)('0');
  592.                     
  593.                     if (c == 'X') (*outputx)('X');
  594.                     if (c == 'x') (*outputx)('x');
  595.  
  596.                     padd(true,precision-length);
  597.                     
  598.                     output_number(value);
  599.                 }
  600.                 else
  601.                 {
  602.                     padd(zero_fill, width - max(precision,length));
  603.                     padd(!zero_fill,precision-length);
  604.                     output_number(value);
  605.                 }
  606.         }  /* ((!zero_fill)&&(!left_justify)) */
  607.         break;
  608.  
  609.         case 'c':
  610.                     /* get the character and readjust the pointer
  611.                         note that a char on the stack is expanded to int */
  612.                         
  613.                     if (left_justify)
  614.                     {
  615.                         (*outputx)(*(int *) argument);
  616.                         padd(BLANKS, width - 1);
  617.                     }
  618.                     else
  619.                     {
  620.                         padd(zero_fill, width - 1);
  621.                         (*outputx)(*(int *) argument);
  622.                     }
  623.                     argument += sizeof (int);
  624.                     break;
  625.  
  626.         case 'p':
  627.             {register char *char_ptr;
  628.  
  629.                     /* get the length of the string */
  630.                     char_ptr = *((char **)argument);
  631.                     length = *char_ptr++;
  632.                     argument += sizeof(char_ptr);
  633.                     
  634.                     /* check for truncation */
  635.                     if (do_precision)
  636.                         if (length > precision) length = precision;
  637.  
  638.                     /* set width to padding width */
  639.                     if ((width -= length) < 0) width = 0;
  640.                     
  641.                     if (left_justify)
  642.                     {
  643.                         while (--length >= 0)
  644.                             (*outputx)(*char_ptr++);
  645.                             
  646.                         padd(BLANKS, width);
  647.                     }
  648.                     else
  649.                     {
  650.                         padd(zero_fill, width);
  651.                         while (--length >= 0)
  652.                             (*outputx)(*char_ptr++);
  653.                     }
  654.                         break;
  655.                 }
  656.  
  657.         case 's':
  658.             {register char *char_ptr;
  659.  
  660.                     /* get the length of the string */
  661.                     
  662.                     length = len_of_str(char_ptr = *((char **) argument));
  663.                     argument += sizeof(char_ptr);
  664.                     
  665.                     /* check for truncation */
  666.                     if (do_precision)
  667.                         if (length > precision) length = precision;
  668.  
  669.                     /* set width to padding width */
  670.                     if ((width -= length) < 0) width = 0;
  671.                     
  672.                     if (left_justify)
  673.                     {
  674.                         while (--length >= 0)
  675.                             (*outputx)(*char_ptr++);
  676.                             
  677.                         padd(BLANKS, width);
  678.                     }
  679.                     else
  680.                     {
  681.                         padd(zero_fill, width);
  682.                         while (--length >= 0)
  683.                             (*outputx)(*char_ptr++);
  684.                     }
  685.                         break;
  686.                 }
  687.  
  688. #ifdef _FORMAT_FP_
  689.  
  690.         case 'f':
  691.                      tempdouble = *((double *)argument);    /* consume argument */
  692.                      argument += sizeof(double);
  693.  
  694.  
  695.                     /* default precision is 6 */
  696.                      if (do_precision == false) precision = 6;
  697. regf:                 
  698.                     bufptr = cvtf2string(&tempdouble, 1, precision, floatbuffer);
  699. nregf:
  700.                     tbufptr = tempbuffer;
  701.                     
  702.                     if ((tempdouble >= 0)&&((space_on)||
  703.                         (sign_on)))
  704.                         *tbufptr++ = (sign_on ? '+' : ' ');
  705.  
  706.                     while(c = *(bufptr++))
  707.                         *tbufptr++ = c;
  708.  
  709.                     if ((pound_on)&&(precision == 0))
  710.                         *tbufptr++ = '.';
  711.  
  712.                     *tbufptr = '\0';
  713.  
  714.                      dopadding(tempbuffer,left_justify,zero_fill,width);
  715.  
  716.                       break;
  717.  
  718.         case 'e':
  719.         case 'E':
  720.                     tempdouble = *((double *)argument);    /* consume argument */
  721.                     argument += sizeof(double);
  722.  
  723.                     /* default precision is 6 */
  724.                     if (do_precision == false) precision = 6;
  725.  
  726.                     bufptr = cvtf2string(&tempdouble, 0, precision+1, floatbuffer);
  727.                     
  728. rege:                
  729.                     tbufptr = tempbuffer;
  730.  
  731.                     if ((tempdouble >= 0)&&(sign_on)) /* if + then make prefix */
  732.                         *bufptr = '+';
  733.  
  734.                     if ((space_on == false)&&(*bufptr == ' '))
  735.                         bufptr++;  /* if leading space and no flag fix it */
  736.  
  737.                     while(*(bufptr))
  738.                     {
  739.                          if (*bufptr == 'e')  /* is this the e char? */
  740.                          {
  741.                             neg = true;
  742.                             *bufptr = c;     /* convert if if necessary */
  743.                             if ((pound_on)&&(precision == 0))
  744.                                 *tbufptr++ = '.';
  745.                         }
  746.                         if ((*(bufptr-2) == c)&&(neg)) /* should we pad the exp */
  747.                             tbufptr = check_for_three(bufptr,tbufptr);
  748.                         if (*bufptr != '@')
  749.                             *tbufptr++ = *bufptr++;
  750.                     }
  751.                     *tbufptr = '\0';
  752.  
  753.                     dopadding(tempbuffer,left_justify,zero_fill,width);
  754.  
  755.                     break;
  756.  
  757.         case 'g':
  758.         case 'G':
  759.                     tempdouble = *((double *)argument);    /* consume argument */
  760.                      argument += sizeof(double);
  761.  
  762.                     if (precision < 1) precision = 1;
  763.  
  764.                     if (do_precision == false) precision = 6;
  765.  
  766.  
  767.                     /* convert to e form */
  768.                     
  769.                     bufptr = cvtf2string(&tempdouble, 0, precision, floatbuffer);
  770.  
  771.                     /* look at char after 'e' */
  772.                     
  773.                     while (*bufptr++ != 'e') 
  774.                         ;
  775.                     neg = (*bufptr++ == '-'); /* is it a negative exponent */
  776.                     tbufptr = bufptr;
  777.  
  778.                     /* get size of exponent */
  779.  
  780.                     length = _std_decode(&tbufptr);
  781.                     if (neg) length *= -1;
  782.  
  783.                     if (pound_on)  /* if # flag is on and ... */
  784.                     {
  785.                         if ((length<=precision)&&(length>=-4))
  786.                             goto regf;  /* do regular f routine */
  787.                         else
  788.                         {
  789.                             /* this gives precision-1 digits after
  790.                                 . instead of precision */
  791.                                 
  792.                             bufptr = (char *)floatbuffer;
  793.                             c -= 2;
  794.                             goto rege;  /* do regular e routine */
  795.                         }
  796.                     }
  797.  
  798.  
  799.                     if ((length<=precision)&&(length>=-4))
  800.                     {register Boolean strip_it = false;
  801.                     
  802.                         /* convert to f format */
  803.  
  804.                         bufptr = cvtf2string(&tempdouble, 1, precision-length, floatbuffer);
  805.  
  806.                         /* don't strip string unless therre is a . */
  807.                         while (*bufptr)
  808.                         {
  809.                             strip_it = strip_it?true:(*bufptr == '.');
  810.                             bufptr++;
  811.                         }
  812.                         bufptr -= 1; /* was 2 */
  813.                         
  814.                         /* strip trailing zeros */
  815.                         if (strip_it)
  816.                         {
  817.                             while (*bufptr == '0') bufptr--;
  818.                             if (*bufptr == '.') bufptr--;
  819.                             *(++bufptr) = '\0';
  820.                         }
  821.                         
  822.                         bufptr = (char *)floatbuffer;
  823.                     
  824.                         /* now test for \0 or -\0 and adjust */
  825.                         if ((*bufptr == '\0') ||
  826.                             ((*bufptr=='-')&&(*(bufptr+1)=='\0')))
  827.                         {
  828.                             *bufptr = '0';
  829.                             *(bufptr+1) = '\0';
  830.                         }
  831.                         
  832.                         goto nregf;
  833.                         
  834.                         break;
  835.                     }
  836.  
  837.  
  838.                     /* back up before the e and strip trailing zeros */
  839.                     
  840.                     bufptr -= 3;
  841.                     
  842.                     while ((*bufptr == '0')||(*bufptr == '.'))
  843.                         *(bufptr--) = '@';
  844.                         
  845.                      /*    bufptr = (char *)floatbuffer;
  846.                          c -= 2;  / convert form g to e, G to E /
  847.                           goto rege;
  848.                       */
  849.  
  850.                     if ((space_on == false)&&(floatbuffer[0] == ' '))
  851.                         floatbuffer[0] = '@';
  852.                         
  853.                     if ((tempdouble>=0) && (sign_on)) floatbuffer[0] = '+';
  854.  
  855.                     tbufptr = (char *)tempbuffer;
  856.                     bufptr = (char *)floatbuffer;
  857.  
  858.                     while (*bufptr != 'e')
  859.                         if (*bufptr != '@')
  860.                             *tbufptr++ = *bufptr++;
  861.                         else
  862.                             bufptr++;
  863.  
  864.                     *bufptr = c-2;  /* convert G to E, g to e */
  865.                     *tbufptr++ = *bufptr++;
  866.                     *tbufptr++ = *bufptr++;
  867.                     tbufptr = check_for_three(bufptr,tbufptr);
  868.                     while (*bufptr)
  869.                         *tbufptr++ = *bufptr++;
  870.                     *tbufptr = '\0';
  871.                     dopadding(tempbuffer,left_justify,zero_fill,width);
  872.  
  873.                     break;
  874. #endif _FORMAT_FP_
  875.  
  876.                 default:
  877.                         /* input garbled, bark: arf arf */
  878.                         return (EOF);
  879.                         
  880.                 } /* end of switch */
  881.         } /* end of if */
  882.         else
  883.             /* copy it directly to output */
  884.             
  885.             (*outputx)(c);
  886.             
  887.     } /* end of while */
  888.         
  889.     return(_num_count);
  890.     
  891.     (void) std_ver();    /*  make the linker drag it in  */
  892. }
  893.